Nachdem ich die letzten beiden Tutorials über Bitmap und Outline Fonts hochgeladen habe, habe ich etlich Emails von Leuten bekommen, die sich gefragt haben, wie man Fonts texturiert. Sie können die automatische Texturkoordinaten Erzeugung nutzen. Diese generiert Texturkoordinaten für jedes Polygon des Fonts.
Eine kleine Anmerkung: dieser Code ist Windows-spezifisch. Er benutzt die wgl Funktionen von Windows um den Font zu erzeugen. Dafür hat Apple aber agl, was das Selbe machen sollte und X hat glx. Unglücklicherweise kann ich Ihnen nicht garantieren, dass der Code portabel ist. Wenn irgendwer einen Plattform unabhängigen Code zum Fonts zeichnen hat, schickt ihn mir und ich werde ein anderes Font-Tutorial schreiben.
Wir erzeugen unser texturiertes Font Demo basierend auf dem Code von Lektion 14. Wenn irgend ein Code in einem bestimmten Abschnitt des Programms geändert wurde, schreibe ich den Codeabschnitt nochmal komplett hier nieder, damit es einfacher ist, Änderungen zu verfolgen.
Der folgende Codeabschnitt ist ähnlich dem aus Lektion 14, aber diesmal inkludieren wir nicht die stdarg.h Datei.
#include < windows.h> // Header Datei für Windows #include < math.h> // Header Datei für Windows Math Library #include < stdio.h> // Header Datei für Standard Input/Output #include < gl\gl.h> // Header Datei für die OpenGL32 Library #include < gl\glu.h> // Header Datei für die GLu32 Library #include < gl\glaux.h> // Header Datei für die GLaux Library HDC hDC=NULL; // Privater GDI Device Context HGLRC hRC=NULL; // Permanenter Rendering Context HWND hWnd=NULL; // Enthält unser Fenster-Handle HINSTANCE hInstance; // Enthält die Instanz der Applikation bool keys[256]; // Array das für die Tastatur Routine verwendet wird bool active=TRUE; // Fenster Aktiv Flag, standardmäßig auf TRUE gesetzt bool fullscreen=TRUE; // Fullscreen Flag ist standardmäßig auf TRUE gesetzt
GLuint texture[1]; // Eine Textur Map ( NEU ) GLuint base; // Basis Display Liste für den Font Satz GLfloat rot; // wird benutzt um den Text rotieren zu lassen LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // Deklaration für WndProc
GLvoid BuildFont(GLvoid) // erzeuge unseren Bitmap Font
{
GLYPHMETRICSFLOAT gmf[256]; // Address Buffer für Font Speicherplatz
HFONT font; // Windows Font ID
base = glGenLists(256); // Speicherplatz für 256 Buchstaben
font = CreateFont( -12, // Höhe unseres Font
0, // Breite unseres Font
0, // Angle Of Escapement
0, // Orientation Angle
FW_BOLD, // Font Dicke
FALSE, // Italic
FALSE, // Underline
FALSE, // Strikeout
SYMBOL_CHARSET, // Character Set Identifier ( Modifiziert )
OUT_TT_PRECIS, // Output Precision CLIP_DEFAULT_PRECIS, // Clipping Precision ANTIALIASED_QUALITY, // Ausgabe Qualität FF_DONTCARE|DEFAULT_PITCH, // Familie And Pitch
"Wingdings"); // Font Name ( Modifiziert )
SelectObject(hDC, font); // wähle den erzeugten Font aus wglUseFontOutlines( hDC, // wähle aktuellen DC 0, // Anfangsbuchstaben 255, // Anzahl der zu erzeugenden Display Listen base, // Anfangs Display Liste
0.1f, // Abweichung vom wahren Umriss
0.2f, // Font Tiefe auf der Z-Ebene WGL_FONT_POLYGONS, // benutze Polygone, keine Linien gmf); // Addresse des Buffer der die Daten empfängt }
AUX_RGBImageRec *LoadBMP(char *Filename) // Lädt ein Bitmap
{
FILE *File=NULL; // Datei Handle
if (!Filename) // gehe sicher, dass ein Dateiname übergeben wurde
{
return NULL; // wenn nicht, gebe NULL zurück
}
File=fopen(Filename,"r"); // überprüfe, ob die Datei existiert
if (File) // Existiert die Datei?
{
fclose(File); // Schließe das Handle
return auxDIBImageLoad(Filename); // Lädt das Bitmap und gibt einen Zeiger zurück
}
return NULL; // Wenn das Laden fehl schlug, gebe NULL zurück
}
int LoadGLTextures() // Lade Bitmaps und konvertiere in Texturen
{
int Status=FALSE; // Status Indikator
AUX_RGBImageRec *TextureImage[1]; // erzeuge Speicherplatz für die Textur
memset(TextureImage,0,sizeof(void *)*1); // Setze den Zeiger auf NULL
if (TextureImage[0]=LoadBMP("Data/Lights.bmp")) // Lade das Bitmap
{
Status=TRUE; // Setze den Status auf TRUE
glGenTextures(1, &texture[0]); // erzeuge die Textur
// erzeuge lineare Mipmapped Textur
glBindTexture(GL_TEXTURE_2D, texture[0]);
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, TextureImage[0]->sizeX,
TextureImage[0]->sizeY, GL_RGB, GL_UNSIGNED_BYTE,
TextureImage[0]->data);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
// Textur-Umriss ist am Objekt befestigt
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
// Textur-Umriss ist am Objekt befestigt
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
glEnable(GL_TEXTURE_GEN_S); // Auto Textur Erzeugung
glEnable(GL_TEXTURE_GEN_T); // Auto Textur Erzeugung
}
if (TextureImage[0]) // Wenn Textur existiert
{
if (TextureImage[0]->data) // Wenn Textur-Image existiert
{
free(TextureImage[0]->data); // gebe Textur-Image Speicher frei
}
free(TextureImage[0]); // gebe die Image-Struktur frei
}
return Status; // gebe Status zurück
}
int InitGL(GLvoid) // Der ganze Setup Kram für OpenGL kommt hier rein
{
if (!LoadGLTextures()) // Rufe Textur Lade Routine auf
{
return FALSE; // wenn Textur nicht geladen wurde, gebe FALSE zurück
}
BuildFont(); // erzeuge den Font
glShadeModel(GL_SMOOTH); // aktiviere Smooth Shading
glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // schwarzer Hintergrund
glClearDepth(1.0f); // Depth Buffer Setup
glEnable(GL_DEPTH_TEST); // aktiviere Depth Testing
glDepthFunc(GL_LEQUAL); // Die Art des auszuführenden Depth Test
glEnable(GL_LIGHT0); // schnelle und schmutzige Beleuchtung (nimmt an, dass Light0 existiert)
glEnable(GL_LIGHTING); // aktiviere Beleuchtung
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // wirklich nette Perspektiven Berechnungen
glEnable(GL_TEXTURE_2D); // aktiviere Textur Mapping glBindTexture(GL_TEXTURE_2D, texture[0]); // wähle Textur aus return TRUE; // Initialisierung war OK }
int DrawGLScene(GLvoid) // Hier kommt der ganze Zeichnen-Kram hin
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Lösche den Bildschirm und den Depth-Buffer
glLoadIdentity(); // Resette die View
// Positioniere den Text glTranslatef(1.1f*float(cos(rot/16.0f)),0.8f*float(sin(rot/20.0f)),-3.0f);
glRotatef(rot,1.0f,0.0f,0.0f); // Rotiere auf der X-Achse glRotatef(rot*1.2f,0.0f,1.0f,0.0f); // Rotiere auf der Y-Achse glRotatef(rot*1.4f,0.0f,0.0f,1.0f); // Rotiere auf der Z-Achse
glTranslatef(-0.35f,-0.35f,0.1f); // zentriere auf der X, Y, Z Achse
glPrint("N"); // zeichne einen Totenkopf mit gekreuzten Knochen
rot+=0.1f; // inkrementiere die Rotations Variable
return TRUE; // Weiter geht's
}
if (!UnregisterClass("OpenGL",hInstance)) // Können wir unsere Klasse de-registrieren
{
MessageBox(NULL,"Could Not Unregister Class.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
hInstance=NULL; // Setze hInstance auf NULL
}
KillFont(); // Zerstöre den Font
}